package pe.com.pgn.consolidadorventas.servidorcentral.service.impl;

import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import org.apache.log4j.Logger;

import pe.com.pgn.consolidadorventas.servidorcentral.dao.ArchivoDao;
import pe.com.pgn.consolidadorventas.servidorcentral.dao.DatabaseObjectDao;
import pe.com.pgn.consolidadorventas.servidorcentral.dao.ServidorCentralDao;
import pe.com.pgn.consolidadorventas.servidorcentral.dbo.Archivo;
import pe.com.pgn.consolidadorventas.servidorcentral.dbo.Estacion;
import pe.com.pgn.consolidadorventas.servidorcentral.dbo.GlpVenta;
import pe.com.pgn.consolidadorventas.servidorcentral.dbo.GlpVentaDetalle;
import pe.com.pgn.consolidadorventas.servidorcentral.dbo.GlpVentaOpBonus;
import pe.com.pgn.consolidadorventas.servidorcentral.dbo.GlpVentaOpDocAnti;
import pe.com.pgn.consolidadorventas.servidorcentral.dbo.GlpVentaOpSalesCard;
import pe.com.pgn.consolidadorventas.servidorcentral.dbo.GlpVentaResumen;
import pe.com.pgn.consolidadorventas.servidorcentral.dbo.GnvVentaDetallada;
import pe.com.pgn.consolidadorventas.servidorcentral.dbo.factory.GlpDboFactory;
import pe.com.pgn.consolidadorventas.servidorcentral.dbo.factory.GnvDboFactory;
import pe.com.pgn.consolidadorventas.servidorcentral.service.ServidorCentralService;
import pe.com.pgn.consolidadorventas.servidorcentral.util.Constantes;
import pe.com.pgn.consolidadorventas.servidorcentral.util.FechasUtil;
import pe.com.pgn.consolidadorventas.servidorcentral.util.LoggerUtil;
import pe.com.pgn.consolidadorventas.servidorcentral.ws.domain.GlpRptaConsultaVenta;
import pe.com.pgn.consolidadorventas.servidorcentral.ws.domain.GnvRptaConsultaVenta;
import pe.com.pgn.consolidadorventas.servidorcentral.ws.domain.glp.GlpRegistroVenta;
import pe.com.pgn.consolidadorventas.servidorcentral.ws.domain.glp.GlpRegistroVentaDetalle;
import pe.com.pgn.consolidadorventas.servidorcentral.ws.domain.glp.GlpRegistroVentaDocAnti;
import pe.com.pgn.consolidadorventas.servidorcentral.ws.domain.glp.GlpRegistroVentaOpBonus;
import pe.com.pgn.consolidadorventas.servidorcentral.ws.domain.glp.GlpRegistroVentaPrincipal;
import pe.com.pgn.consolidadorventas.servidorcentral.ws.domain.glp.GlpRegistroVentaSalesCard;
import pe.com.pgn.consolidadorventas.servidorcentral.ws.domain.gnv.GnvRegistroVenta;

public class ServidorCentralServiceImpl implements ServidorCentralService{

	static Logger logger = Logger.getLogger(ServidorCentralServiceImpl.class);
	
	DatabaseObjectDao databaseObjectDao;
	ArchivoDao archivoDao;
	ServidorCentralDao servidorCentralGlpDao;
	ServidorCentralDao servidorCentralGnvDao;
    Constantes constantes;
			
	SimpleDateFormat formato;
	SimpleDateFormat formatoFechaHora;
	
	public ServidorCentralServiceImpl(){
		formato = new SimpleDateFormat(Constantes.FORMATO_FECHA);
		formatoFechaHora = new SimpleDateFormat(Constantes.FORMATO_FECHA_HORA);
	}

	//@Transactional(propagation=Propagation.REQUIRED,isolation=Isolation.READ_COMMITTED,readOnly=false)	
	public void consolidarInformacionEstacion(Estacion e,Date fecha,int tipoConsolidacion){
		String strFecha = formato.format(fecha);
		String datosEstacion = "["+e.getCodEstacion()+"] "+e.getNombreEstacion()+" ["+e.getIp()+":"+e.getPuerto()+"]";
		Archivo aux = null;
		
		//Para GLP
		if(tipoConsolidacion==Constantes.TIPO_VENTA_GLP){
			//Verificamos que la estacion no tenga un archivo de glp para la fecha indicada
			aux = archivoDao.consultarCargaDelDia(e.getIdEstacion(),fecha,Constantes.TIPO_ARCHIVO_GLP);
			GlpRptaConsultaVenta rptaGlp = null;
			if(aux==null){
				LoggerUtil.info(logger,"====================================================");
				LoggerUtil.info(logger,"Estacion : "+datosEstacion);
				LoggerUtil.info(logger,"Inicio para consolidar estacion");
				
				try{
					rptaGlp=(GlpRptaConsultaVenta)servidorCentralGlpDao.consultarInformacionVentasPorDia(e,strFecha,Constantes.TIPO_ARCHIVO_GLP);	
					registrarRptaConsultaVentaGlp(e,aux,rptaGlp,fecha);
				}catch(Exception ex){
					LoggerUtil.error(logger,"Excepcion no controlada para la estacion : "+datosEstacion+" ( "+ex.getMessage()+" )");
				}
				
				LoggerUtil.info(logger,"Fin consolidacion de estacion");
				LoggerUtil.info(logger,"====================================================");
			}
		}
		
		//Para GNV
		if(tipoConsolidacion==Constantes.TIPO_VENTA_GNV){
			//Verificamos que la estacion no tenga un archivo de gnv para la fecha indicada
			aux = archivoDao.consultarCargaDelDia(e.getIdEstacion(),fecha,Constantes.TIPO_ARCHIVO_GNV);
			GnvRptaConsultaVenta rptaGnv = null;
			if(aux==null){
				LoggerUtil.info(logger,"====================================================");
				LoggerUtil.info(logger,"Estacion :"+datosEstacion);
				LoggerUtil.info(logger,"Inicio para consolidar estacion");
				
				try{
					rptaGnv = (GnvRptaConsultaVenta)servidorCentralGnvDao.consultarInformacionVentasPorDia(e, strFecha, Constantes.TIPO_ARCHIVO_GNV);
					registrarRptaConsultaVentaGnv(e, aux, rptaGnv, fecha);
				}catch(Exception ex){
					LoggerUtil.error(logger,"Excepcion no controlada para la estacion : "+datosEstacion+" ( "+ex.getMessage()+" )");
				}
				
				LoggerUtil.info(logger,"Fin consolidacion de estacion");
				LoggerUtil.info(logger,"====================================================");
			}
		}
	}
	
	//@Transactional(propagation=Propagation.REQUIRED,isolation=Isolation.READ_COMMITTED,readOnly=false)	
	public void regenerarInformacionVentas(int idEstacion, String strFecha,int tipoCombustible) {
		Estacion e = databaseObjectDao.findById(Estacion.class, idEstacion);
		String datosEstacion = "["+e.getCodEstacion()+"] "+e.getNombreEstacion()+" ["+e.getIp()+":"+e.getPuerto()+"]";

		//Reenvio para glp
		LoggerUtil.info(logger,"====================================================");
		LoggerUtil.info(logger,"Estacion : "+datosEstacion);
		
		if(tipoCombustible==Constantes.TIPO_ARCHIVO_GLP){
			LoggerUtil.info(logger,"Inicio reenvio GLP");
		}
		if(tipoCombustible==Constantes.TIPO_ARCHIVO_GNV){
			LoggerUtil.info(logger,"Inicio reenvio GNV");
		}
		
		Archivo aux = archivoDao.consultarCargaDelDia(e.getIdEstacion(),strFecha,tipoCombustible);
		
		Date fecha = null;
		try {
			fecha = formato.parse(strFecha);
		} catch (ParseException e1) {
			LoggerUtil.error(logger,e1.getMessage());
		}
		
		//Solo ha habido error en la carga se debe llamar
		GlpRptaConsultaVenta rptaGlp = null;
		GnvRptaConsultaVenta rptaGnv = null;
		if(aux!=null){
			if(aux.getTipoCarga()==Constantes.TIPO_CARGA_ERROR){
				//Si es glp regeneramos glp
				
				if(tipoCombustible==Constantes.TIPO_ARCHIVO_GLP){
					rptaGlp=(GlpRptaConsultaVenta)servidorCentralGlpDao.consultarInformacionVentasPorDia(e,strFecha,Constantes.TIPO_ARCHIVO_GLP);
					try{
						registrarRptaConsultaVentaGlp(e,aux,rptaGlp,fecha);
					}catch(Exception ex){
						LoggerUtil.error(logger,"Exception en el registro , se realizo rollback :"+ex.getMessage());
					}
				}
				
				if(tipoCombustible==Constantes.TIPO_ARCHIVO_GNV){
					rptaGnv=(GnvRptaConsultaVenta)servidorCentralGnvDao.consultarInformacionVentasPorDia(e,strFecha,Constantes.TIPO_ARCHIVO_GNV);

					try{
						registrarRptaConsultaVentaGnv(e,aux,rptaGnv,fecha);
					}catch(Exception ex){
						LoggerUtil.error(logger,"Exception en el registro , se realizo rollback :"+ex.getLocalizedMessage());
					}
				}
				 
			}
		}else{
			
			//Como no existe el archivo sera la primera llamada , pero debemos inicializarlo para que sea carga manual
			aux = new Archivo();
			aux.setIdEstacion(e.getIdEstacion());
			aux.setFecha(FechasUtil.formatearStringToDate(strFecha));
			aux.setTipoArchivo(tipoCombustible);
			
			if(tipoCombustible==Constantes.TIPO_ARCHIVO_GLP){
				rptaGlp=(GlpRptaConsultaVenta)servidorCentralGlpDao.consultarInformacionVentasPorDia(e,strFecha,Constantes.TIPO_ARCHIVO_GLP);
				try{
					registrarRptaConsultaVentaGlp(e,aux,rptaGlp,fecha);					
				}catch(Exception ex){
					LoggerUtil.error(logger,"Exception en el registro , se realizo rollback :"+ex.getMessage());
				}
			}
			
			if(tipoCombustible==Constantes.TIPO_ARCHIVO_GNV){
				rptaGnv=(GnvRptaConsultaVenta)servidorCentralGnvDao.consultarInformacionVentasPorDia(e,strFecha,Constantes.TIPO_ARCHIVO_GNV);
				try{
					registrarRptaConsultaVentaGnv(e,aux,rptaGnv,fecha);
				}catch(Exception ex){
					LoggerUtil.error(logger,"Exception en el registro , se realizo rollback :"+ex.getMessage());
				}	
			}
		}
		
		if(tipoCombustible==Constantes.TIPO_ARCHIVO_GLP){
			LoggerUtil.info(logger,"Fin reenvio GLP");
		}
		if(tipoCombustible==Constantes.TIPO_ARCHIVO_GNV){
			LoggerUtil.info(logger,"Fin reenvio GNV");
		}
		LoggerUtil.info(logger,"====================================================");
		
	}
	
	@SuppressWarnings("unchecked")
	//@Transactional(propagation=Propagation.REQUIRED,isolation=Isolation.READ_COMMITTED,readOnly=false,rollbackFor=Exception.class)
	public void registrarRptaConsultaVentaGlp(Estacion e,Archivo a,GlpRptaConsultaVenta rptaGlp,Date fecha) throws Exception{
		Calendar cx;
		int tipoRespuesta = rptaGlp.getTipoRespuesta();
		Archivo archivoGlp = null;
		
		if(a!=null){
			//Es una actualizacion
			archivoGlp = a;
		}else{
			//Es la primera vez que se llama al registro
			archivoGlp = new Archivo();
			archivoGlp.setIdEstacion(e.getIdEstacion());
			archivoGlp.setFecha(fecha);
			archivoGlp.setTipoArchivo(Constantes.TIPO_ARCHIVO_GLP);
		}
			
		if(tipoRespuesta == -1 || tipoRespuesta == 0 ){
			//-1 no habia ninguno de los archivos
			//0 solo estaba el archivo de error
			archivoGlp.setTipoCarga(Constantes.TIPO_CARGA_ERROR);
			archivoGlp.setDescripcionCarga(rptaGlp.getMensajeError());
			databaseObjectDao.persist(archivoGlp);
		}
		
		if(tipoRespuesta == 1){
			
			if(a==null){
				//No se encontro el archivo , por ende es carga automatica
				archivoGlp.setTipoCarga(Constantes.TIPO_CARGA_AUTOMATICA);
				archivoGlp.setDescripcionCarga("Carga Automatica");
			}else{
				//Como ya existe es carga manual
				archivoGlp.setTipoCarga(Constantes.TIPO_CARGA_MANUAL);
				cx = Calendar.getInstance();
				archivoGlp.setDescripcionCarga("Carga manual ( "+formatoFechaHora.format(cx.getTime())+" )");
			}
			databaseObjectDao.persist(archivoGlp);
		
			//Tenemos que guardar los datos
			
			//Recogemos las ventas
			List<GlpRegistroVenta> ventas = rptaGlp.getListaVentas();
			int dim = ventas.size();
			
			try{
				LoggerUtil.info(logger,"Registrando datos de GLP");
				for(int j=0;j<dim;j++){
					//Guardamos el dato principal
					GlpRegistroVenta grv = ventas.get(j);
					GlpRegistroVentaPrincipal p = grv.getPrincipal();
					GlpVenta v = GlpDboFactory.generarDboGlpVenta(archivoGlp, p);
					databaseObjectDao.persist(v);
					
					//Guardamos los detalles
					List<GlpRegistroVentaDetalle> listaDetalles = grv.getDetalles();
					List<GlpVentaDetalle> listaDboDetalles = (List<GlpVentaDetalle>)GlpDboFactory.generarListaDbo(v,listaDetalles,2);
					databaseObjectDao.persist(listaDboDetalles);
					
					//Guardamos los salescards
					List<GlpRegistroVentaSalesCard> listaSalesCards = grv.getSalesCards();
					List<GlpVentaOpSalesCard> listaDboSalesCard = (List<GlpVentaOpSalesCard>)GlpDboFactory.generarListaDbo(v,listaSalesCards,3);
					databaseObjectDao.persist(listaDboSalesCard);
					
					//Registramos los opDocAntis
					List<GlpRegistroVentaDocAnti> listaOpDocAnti = grv.getDocAntis();
					List<GlpVentaOpDocAnti> listaDboOpDocAnti = (List<GlpVentaOpDocAnti>)GlpDboFactory.generarListaDbo(v, listaOpDocAnti,4);
					databaseObjectDao.persist(listaDboOpDocAnti);
					
					//Registramos los opBonus
					List<GlpRegistroVentaOpBonus> listaOpBonus = grv.getOpBonus();
					List<GlpVentaOpBonus> listaDboOpBonus = (List<GlpVentaOpBonus>)GlpDboFactory.generarListaDbo(v, listaOpBonus, 5);
					databaseObjectDao.persist(listaDboOpBonus);

				}
				
				//Guardamos el resumen
				GlpVentaResumen rs = new GlpVentaResumen();
				LoggerUtil.debug(logger,"Registrando resumen del archivo :"+archivoGlp.getIdArchivo());
				rs.setIdArchivo(archivoGlp.getIdArchivo());
				rs.setCantidadVentas(rptaGlp.getCantidadVentas());
				
				try{
					rs.setTotalVentasPen(new BigDecimal(rptaGlp.getVentaTotal()));					
				}catch(Exception ex){
					LoggerUtil.error(logger, "Error en el total de ventas");
				}
				
				databaseObjectDao.persist(rs);
				LoggerUtil.debug(logger,"Fin registro resumen del archivo :"+archivoGlp.getIdArchivo());
				
				LoggerUtil.info(logger,"Fin de registro datos GLP");
				
			}catch(Exception x){
				LoggerUtil.error(logger,"Excepcion al registrar el archivo ["+archivoGlp.getIdArchivo()+"] con fecha "+FechasUtil.formatearDateToString(fecha)+" : "+x.getLocalizedMessage());
				throw new Exception(x.getLocalizedMessage());
			}
		}
	}
	
	//@Transactional(propagation=Propagation.REQUIRED,isolation=Isolation.READ_COMMITTED,readOnly=false,rollbackFor=Exception.class)
	public void registrarRptaConsultaVentaGnv(Estacion e, Archivo a,GnvRptaConsultaVenta rptaGnv, Date fecha) throws Exception {
		Calendar cx;
		int tipoRespuesta = rptaGnv.getTipoRespuesta();
		Archivo archivoGnv = null;
		
		if(a!=null){
			//Es una actualizacion
			archivoGnv = a;
		}else{
			//Es la primera vez que se llama al registro
			archivoGnv = new Archivo();
			archivoGnv.setIdEstacion(e.getIdEstacion());
			archivoGnv.setFecha(fecha);
			archivoGnv.setTipoArchivo(Constantes.TIPO_ARCHIVO_GNV);
		}
			
		if(tipoRespuesta == -1 || tipoRespuesta == 0 ){
			//-1 no habia ninguno de los archivos
			//0 solo estaba el archivo de error
			archivoGnv.setTipoCarga(Constantes.TIPO_CARGA_ERROR);
			archivoGnv.setDescripcionCarga(rptaGnv.getMensajeError());
			databaseObjectDao.persist(archivoGnv);
		}
		
		if(tipoRespuesta == 1){
			if(a==null){
				//No se encontro el archivo , por ende es carga automatica
				archivoGnv.setTipoCarga(Constantes.TIPO_CARGA_AUTOMATICA);
				archivoGnv.setDescripcionCarga("Carga Automatica");
			}else{
				//Como ya existe es carga manual
				archivoGnv.setTipoCarga(Constantes.TIPO_CARGA_MANUAL);
				cx = Calendar.getInstance();
				archivoGnv.setDescripcionCarga("Carga manual ( "+formatoFechaHora.format(cx.getTime())+" )");
			}
			databaseObjectDao.persist(archivoGnv);
			
			List<GnvRegistroVenta> ventas = rptaGnv.getListaVentas();
			int dim = ventas.size();
			
			try{
				LoggerUtil.info(logger,"Registrando datos de GNV");
				for(int j=0;j<dim;j++){
					GnvRegistroVenta g = ventas.get(j);
					GnvVentaDetallada vta = GnvDboFactory.generarDboVentaDetallada(g,rptaGnv.getCodEstacion());
					databaseObjectDao.persist(vta);
				}
				LoggerUtil.info(logger,"Fin de registro datos GNV");
			}catch(Exception ex){
				LoggerUtil.error(logger,"No se pudo registrar los datos de GNV : "+ex.getMessage());
				throw new Exception(ex.getLocalizedMessage());
			}
		}
		
	}

	public DatabaseObjectDao getDatabaseObjectDao() {
		return databaseObjectDao;
	}

	public void setDatabaseObjectDao(DatabaseObjectDao databaseObjectDao) {
		this.databaseObjectDao = databaseObjectDao;
	}

	public ArchivoDao getArchivoDao() {
		return archivoDao;
	}

	public void setArchivoDao(ArchivoDao archivoDao) {
		this.archivoDao = archivoDao;
	}

	public ServidorCentralDao getServidorCentralGlpDao() {
		return servidorCentralGlpDao;
	}

	public void setServidorCentralGlpDao(ServidorCentralDao servidorCentralGlpDao) {
		this.servidorCentralGlpDao = servidorCentralGlpDao;
	}

	public ServidorCentralDao getServidorCentralGnvDao() {
		return servidorCentralGnvDao;
	}

	public void setServidorCentralGnvDao(ServidorCentralDao servidorCentralGnvDao) {
		this.servidorCentralGnvDao = servidorCentralGnvDao;
	}

	public Constantes getConstantes() {
		return constantes;
	}

	public void setConstantes(Constantes constantes) {
		this.constantes = constantes;
	}
}
